#include <stdio.h>
#include <jni.h>
#include <android/native_activity.h>
#include <android/input.h>
#include <android/log.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <EGL/egl.h>

#define printf(...) __android_log_print(ANDROID_LOG_INFO, "stdout", __VA_ARGS__)

static ANativeActivity* curview;

static EGLDisplay egl_display_;
static EGLSurface egl_surface_;
static EGLContext egl_context_;

static int egl_create(ANativeWindow* window){
    const EGLint attribs[] = {
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_BLUE_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_RED_SIZE, 8,
        EGL_NONE
    };
    EGLConfig config;
    EGLint numConfigs;
    EGLint format;

    egl_display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);  
    eglInitialize(egl_display_, 0, 0);
    eglChooseConfig(egl_display_, attribs, &config, 1, &numConfigs);
    eglGetConfigAttrib(egl_display_, config, EGL_NATIVE_VISUAL_ID, &format);
    ANativeWindow_setBuffersGeometry(window, 0, 0, format);
    egl_surface_ = eglCreateWindowSurface(egl_display_, config, window, NULL);
    egl_context_ = eglCreateContext(egl_display_, config, NULL, NULL);
    if (eglMakeCurrent(egl_display_, egl_surface_, egl_surface_, egl_context_) == EGL_FALSE) {
        printf("Unable to eglMakeCurrent\n");       
        return -1;
    }
    return 0;
}

static void egl_destroy(){
    eglDestroyContext(egl_display_, egl_context_);
    eglDestroySurface(egl_display_, egl_surface_);    
    eglTerminate(egl_display_);
}

int onALooperCallback(int fd, int events, void* data){
	//printf("onALooperCallback: %d -- %d -- %p\n", fd,events,data);
	int i;
	AInputQueue* queue = (AInputQueue*)data;
	AInputEvent* event = NULL;
	int count = AInputQueue_getEvent(queue,&event);
    if(count <0)return 1;
	int type = AInputEvent_getType(event);
	if(type == AINPUT_EVENT_TYPE_KEY){
		int code = AKeyEvent_getKeyCode(event);
		int act = AKeyEvent_getAction(event);
		printf("Key Event: {action:%d,keycode:%d} \n", act, code);
		if(act == AKEY_EVENT_ACTION_UP && code == AKEYCODE_BACK){
			ANativeActivity_finish(curview);
		}
		AInputQueue_finishEvent(queue,event,1);
	}else if(type == AINPUT_EVENT_TYPE_MOTION){
		int act = AMotionEvent_getAction(event);
		//int xo = AMotionEvent_getXOffset(event);
		//int yo = AMotionEvent_getYOffset(event);
		//int xp = AMotionEvent_getXPrecision(event);
		//int yp = AMotionEvent_getYPrecision(event);
		int pc = AMotionEvent_getPointerCount(event);
		printf("Motion Event:{action:%d,pointer_count:%d}\n",act,pc);
		for(i=0;i<pc;++i){
			int x = AMotionEvent_getX(event,i);
			int y = AMotionEvent_getY(event,i);
			printf("    {x:%d,y:%d}\n",x,y);
		}
		AInputQueue_finishEvent(queue,event,1);
	}
	return 1;
}



static void onDestroy(ANativeActivity* activity) {
    printf("Destroy: %p\n", activity);    
}

static void onStart(ANativeActivity* activity) {
    printf("Start: %p\n", activity);
    
}

static void onStop(ANativeActivity* activity) {
    printf("Stop: %p\n", activity);
    
}

static void onResume(ANativeActivity* activity) {
    printf("Resume: %p\n", activity);
    
}

static void onPause(ANativeActivity* activity) {
    printf("Pause: %p\n", activity);    
    //net_term();
}

static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
    printf("SaveInstanceState: %p\n", activity);

    return NULL;
}

static void onConfigurationChanged(ANativeActivity* activity) {
    //struct android_app* android_app = (struct android_app*)activity->instance;
    printf("ConfigurationChanged: %p\n", activity);
}

static void onLowMemory(ANativeActivity* activity) {
    printf("LowMemory: %p\n", activity);
}

static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
    printf("WindowFocusChanged: %p -- %d\n", activity, focused);
}


static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
    printf("NativeWindowCreated: %p -- %p\n", activity, window); 
	egl_create(window);
}

static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
    printf("NativeWindowDestroyed: %p -- %p\n", activity, window);    
	egl_destroy();
}

static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
	ALooper* l = ALooper_forThread();
    printf("InputQueueCreated: %p -- %p\n", activity, queue);
    AInputQueue_attachLooper(queue,l,199999,onALooperCallback,queue);    
}

static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
    printf("InputQueueDestroyed: %p -- %p\n", activity, queue);
    AInputQueue_detachLooper(queue);    
}

static void onContentRectChanged(ANativeActivity* activity,const ARect* r) {
    printf("onContentRectChanged: %p - {%d,%d,%d,%d}\n", activity,r->left,r->top,r->right,r->bottom);  	
}

static void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* w) {
    printf("onNativeWindowRedrawNeeded: %p\n", activity); 
	eglSwapBuffers(egl_display_, egl_surface_);
}
static void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* w) {
    printf("onNativeWindowResized: %p\n", activity);
}


int app_main_loop(){
    return 0;
}

extern int app_main(int argc, char* argv[]);

void ANativeActivity_onCreate(ANativeActivity* activity,
        void* savedState, size_t savedStateSize) {            
    //logx_init(activity, ANDROID_LOG_INFO);
	curview = activity;

	printf("ANativeActivity_onCreate %p\n", activity);
	activity->callbacks->onConfigurationChanged = onConfigurationChanged;
	activity->callbacks->onContentRectChanged  = onContentRectChanged;
	activity->callbacks->onDestroy = onDestroy;
	activity->callbacks->onInputQueueCreated = onInputQueueCreated;
	activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
	activity->callbacks->onLowMemory = onLowMemory;
	activity->callbacks->onNativeWindowCreated =  onNativeWindowCreated;
	activity->callbacks->onNativeWindowDestroyed =  onNativeWindowDestroyed;
	activity->callbacks->onNativeWindowRedrawNeeded =  onNativeWindowRedrawNeeded;
	activity->callbacks->onNativeWindowResized =  onNativeWindowResized;
	activity->callbacks->onPause = onPause;
	activity->callbacks->onResume = onResume;
	activity->callbacks->onSaveInstanceState = onSaveInstanceState;
	activity->callbacks->onStart = onStart;
	activity->callbacks->onStop = onStop;
	activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;

    app_main(1, NULL);	
}


